package pl.diagnoser.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.fields.DataSourceFloatField;
import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
import pl.diagnoser.client.dto.DiagnoserResultDTO;
import pl.diagnoser.client.dto.ObjectsDTO;
import pl.diagnoser.client.tools.DataGetterService;
import pl.diagnoser.client.tools.DataGetterServiceAsync;
import pl.diagnoser.client.tools.DiagnoserProperties;
import pl.diagnoser.client.tools.SearchObjectAttribute;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.form.FormItemValueFormatter;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.CanvasItem;
import com.smartgwt.client.widgets.form.fields.DateItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;

public class SearchObjects extends Canvas {

	private ObjectDetailsForm searchForm;
	private Button fastSearchButton;
	private Button slowSearchButton;
	private Button saveSearching;
	private Button newSearchButton;
	private HLayout mainLayout;
	private VLayout searchResultLayout;
	private VLayout buttonLayout;
	private DynamicForm form = new DynamicForm();
	private SelectItem searchResultSelector;
	private DataSource dataSource;
	private final static Double PEWNY = 1.00;
	private final static Double RACZEJ_PEWNY = 0.75;
	private final static Double RACZEJ_NIEPEWNY = 0.50;
	private final static Double NIEPEWNY = 0.25;
	public final static Integer PEWNOSC_COLUMN_SIZE = 60;
	private ObjectDetailsForm objectDetailsForm;
	private final DiagnoserProperties properties = new DiagnoserProperties();
	private List<SearchObjectAttribute> searchCriteria = new ArrayList<SearchObjectAttribute>();
	private List<SearchObjectAttribute> emptySearchCriteria = new ArrayList<SearchObjectAttribute>();

	SearchObjects() {
		this.setWidth100();
		this.setHeight100();
		
		//dataSource = SerachResultDataSource.getInstance();
		dataSource = new SerachResultDataSource("searchDS");
		mainLayout = new HLayout();
		mainLayout.setWidth100();
		mainLayout.setHeight100();
		mainLayout.setLeft(10);
		mainLayout.setTop(5);
		mainLayout.setMembersMargin(5);

		searchForm = new ObjectDetailsForm(false, true, false, false);
		searchForm.setWidth(430);
		
		buttonLayout = new VLayout();
		buttonLayout.setHeight100();
		buttonLayout.setWidth(130);
		buttonLayout.setMembersMargin(5);
		
        fastSearchButton = new Button();
        fastSearchButton.setWidth(130);
        //fastSearchButton.setTitle("Szybkie szukanie");
        fastSearchButton.setTitle("fastSearchButton");
        properties.getWidgetTitle("fastSearchButton", fastSearchButton);
        fastSearchButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				prepareSearchData(true);
			}
		});
        buttonLayout.addMember(fastSearchButton);
        
        slowSearchButton = new Button();
        slowSearchButton.setWidth(170);
        //slowSearchButton.setTitle("Wolne szukanie");
        slowSearchButton.setTitle("slowSearchButton");
        properties.getWidgetTitle("slowSearchButton", slowSearchButton);
        slowSearchButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				prepareSearchData(false);
			}
		});
        buttonLayout.addMember(slowSearchButton);
        
        newSearchButton = new Button();
        newSearchButton.setWidth(120);
        newSearchButton.setTitle("Nowe wyszukiwanie");
        newSearchButton.setVisible(false);
        newSearchButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				searchForm.clearForm();
				objectDetailsForm.clearForm();
				searchCriteria.clear();
				emptySearchCriteria.clear();
				for( ListGridRecord test : searchResultSelector.getClientPickListData())
					dataSource.removeData(test);
				searchResultLayout.hide();
				newSearchButton.hide();
				saveSearching.hide();
			}
		});
        buttonLayout.addMember(newSearchButton);
        
        saveSearching = new Button();
        saveSearching.setTitle("Zapisz wyszukiwanie");
        saveSearching.setVisible(false);
        saveSearching.setWidth(120);
        saveSearching.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				saveSearching();
			}
		});
        buttonLayout.addMember(saveSearching);
        
        //searchResultLayout = new HLayout();
        searchResultLayout = new VLayout();
        searchResultLayout.setShowEdges(true);
        searchResultLayout.setWidth(410);
        searchResultLayout.setHeight100();
        searchResultLayout.setVisible(false);
        searchResultLayout.setMembersMargin(5);
        
        objectDetailsForm = new ObjectDetailsForm(new ObjectsDTO("",Long.parseLong("0")), false, false, false);
        //objectDetailsForm.setWidth(275);
        objectDetailsForm.setWidth(400);
        objectDetailsForm.setAlign(Alignment.CENTER);
        
        final ListGridField objectId = new ListGridField("objectId");
        objectId.setType(ListGridFieldType.INTEGER);
        objectId.setHidden(true);
        
        final ListGridField objectName = new ListGridField("objectName","Innowacja");
        objectName.setType(ListGridFieldType.TEXT);
        
        final ListGridField objectConfidence = new ListGridField("objectConfidence", "Pewność", SearchObjects.PEWNOSC_COLUMN_SIZE);
        objectConfidence.setType(ListGridFieldType.FLOAT);
        
        searchResultSelector = new SelectItem();
        searchResultSelector.setShowTitle(false);
        searchResultSelector.setValueField("objectId");
        searchResultSelector.setDisplayField("objectName");
        searchResultSelector.setPickListFields(objectId, objectName, objectConfidence);
        searchResultSelector.setWidth(400);
        searchResultSelector.setPickListWidth(400);
        searchResultSelector.setDefaultToFirstOption(true);
        searchResultSelector.setOptionDataSource(dataSource);
        searchResultSelector.setValueFormatter(new FormItemValueFormatter() {  
            public String formatValue(Object value, Record record, DynamicForm form, FormItem item) {  
                ListGridRecord r = item.getSelectedRecord();  
                if (r == null) return "";  
                return r.getAttribute("objectName") + " : " + r.getAttribute("objectConfidence");  
            }  
        });
        searchResultSelector.addChangedHandler(new ChangedHandler() {
			public void onChanged(ChangedEvent event) {
				objectDetailsForm.clearValues();
				objectDetailsForm.getObjectAttributes(Long.parseLong(event.getItem().getSelectedRecord().getAttributeAsString("objectId")));
			}
		});
        form.setItems(searchResultSelector);
        searchResultLayout.addMember(form);
		searchResultLayout.addMember(objectDetailsForm);
		
        mainLayout.addMember(searchForm);
        mainLayout.addMember(buttonLayout);
        mainLayout.addMember(searchResultLayout);
        
        this.addChild(mainLayout);
        this.draw();
        
	}
	
	private void prepareSearchData(boolean isFast) {
		List<FormItem> formItems = Arrays.asList(searchForm.getFields());
		for(FormItem formItem : formItems) {
			if(formItem.isVisible() && !formItem.getName().equals("combo") && !formItem.getName().contains("confidenceSelectItem_"))
			{
				if(formItem instanceof SelectItem) {
					SelectItem tmpSelectItem = (SelectItem) formItem;
					SearchObjectAttribute tmpSearchObjectAttribute = new SearchObjectAttribute(formItem.getName());
					tmpSearchObjectAttribute.setConfidence(getConfidence((String) searchForm.getField("confidenceSelectItem_" + formItem.getName()).getDisplayValue()));
					
					if(!tmpSelectItem.getDisplayValue().isEmpty() && !tmpSelectItem.getDisplayValue().contains("--")) {
						tmpSearchObjectAttribute.addAttributeValue(tmpSelectItem.getDisplayValue());
						searchCriteria.add(tmpSearchObjectAttribute);	
					} else if(tmpSelectItem.getDisplayValue().isEmpty() && searchForm.getField(formItem.getName() + "_ci") == null) {
						//tmpSearchObjectAttribute.loadEmptyAttributeValues();
						emptySearchCriteria.add(tmpSearchObjectAttribute);
					}
				}
				else if(formItem instanceof TextItem){
					TextItem tmpTextItem = (TextItem) formItem;
					SearchObjectAttribute tmpSearchObjectAttribute = new SearchObjectAttribute(formItem.getName());
					tmpSearchObjectAttribute.setConfidence(getConfidence((String) searchForm.getField("confidenceSelectItem_" + formItem.getName()).getDisplayValue()));
					if(!tmpTextItem.getDisplayValue().isEmpty()) {
						tmpSearchObjectAttribute.addAttributeValue(tmpTextItem.getDisplayValue());
						searchCriteria.add(tmpSearchObjectAttribute);
					} else if(tmpTextItem.getDisplayValue().isEmpty() && searchForm.getField(formItem.getName() + "_ci") == null) {
						//tmpSearchObjectAttribute.loadEmptyAttributeValues(emptySearchCriteria);
						emptySearchCriteria.add(tmpSearchObjectAttribute);
					}
				}
				else if(formItem instanceof DateItem){
					DateItem tmpDateItem = (DateItem) formItem;
					SearchObjectAttribute tmpSearchObjectAttribute = new SearchObjectAttribute(formItem.getName());
					if(tmpDateItem.getDisplayValue() != null && !tmpDateItem.getDisplayValue().isEmpty()) {
						tmpSearchObjectAttribute.setConfidence(getConfidence((String) searchForm.getField("confidenceSelectItem_" + formItem.getName()).getDisplayValue()));
						tmpSearchObjectAttribute.addAttributeValue(tmpDateItem.getDisplayValue());
						searchCriteria.add(tmpSearchObjectAttribute);
					} else if(tmpDateItem.getDisplayValue() != null && tmpDateItem.getDisplayValue().isEmpty()) {
						//tmpSearchObjectAttribute.loadEmptyAttributeValues();
						emptySearchCriteria.add(tmpSearchObjectAttribute);
					}
				}
				else if(formItem instanceof ButtonItem) {}
				else if(formItem instanceof CanvasItem) {
					ListGrid tmpListGridItem = ((ListGrid)((CanvasItem) formItem).getCanvas());
					if(tmpListGridItem.isVisible()) {
						SearchObjectAttribute tmpSearchObjectAttribute = new SearchObjectAttribute(formItem.getName().replace("_ci", "").toLowerCase());
						tmpSearchObjectAttribute.setConfidence(getConfidence((String) searchForm.getField("confidenceSelectItem_" + formItem.getName().replace("_ci", "").toLowerCase()).getDisplayValue()));
						if(tmpListGridItem.getRecords().length > 0) {
							
							for(ListGridRecord record : Arrays.asList(tmpListGridItem.getRecords())) {
								String tmpValue = record.getAttributeAsString(formItem.getName().replace("_ci", "").toLowerCase() + "_lg");
								tmpSearchObjectAttribute.addAttributeValue(tmpValue);
							}
							searchCriteria.add(tmpSearchObjectAttribute);
						} else {
							//tmpSearchObjectAttribute.loadEmptyAttributeValues();
							emptySearchCriteria.add(tmpSearchObjectAttribute);
						}
					}
				}
			}
		}
		getFoundObjectList(isFast);
	}
	
	private void getFoundObjectList(boolean isFast) {
		
		DataGetterServiceAsync dataGetterAsc = GWT.create(DataGetterService.class);
		
		AsyncCallback<List<DiagnoserResultDTO>> callback = new AsyncCallback<List<DiagnoserResultDTO>>() {
			
			public void onFailure(Throwable caught) {
				System.out.println(caught.getMessage());
			}

			public void onSuccess(List<DiagnoserResultDTO> result) {
				if(result != null) {
					int i = 0;
					for(DiagnoserResultDTO tmpResult : result) {
						i++;
						dataSource.addData(new SerachResultRecord(tmpResult.getDiagnoserResultId(), tmpResult.getDiagnoserResultName(), tmpResult.getDiagnoserResultConfidence()));
						if(i==1)
							objectDetailsForm.getObjectAttributes(tmpResult.getDiagnoserResultId());
					}
					
					saveSearching.show();
					searchResultLayout.show();
					newSearchButton.show();
					searchResultSelector.redraw();
				}
			}
		};
		
		dataGetterAsc.getPossibleDefects(searchCriteria, emptySearchCriteria, true, callback);
	}
	
	private void saveSearching() {
		DataGetterServiceAsync dataGetterAsc = GWT.create(DataGetterService.class);
		
		AsyncCallback<String> callback = new AsyncCallback<String>() {
			
			public void onFailure(Throwable caught) {
				System.out.println(caught.getMessage());
			}

			public void onSuccess(String result) {
				if(!result.equals("OK"))
					SC.say(result);
			}
		};
		if(searchResultSelector.getSelectedRecord().getAttributeAsString("objectId") != null)
			dataGetterAsc.saveSearching(searchCriteria, Long.parseLong(searchResultSelector.getSelectedRecord().getAttributeAsString("objectId")), callback);
	}
	
	private Double getConfidence(String confidenceName) {
		if(confidenceName == null)
			return null;
		
		if(confidenceName.equals("Pewny"))
			return PEWNY;
		else if(confidenceName.equals("Raczej pewny"))
			return RACZEJ_PEWNY;
		else if(confidenceName.equals("Raczej niepewny"))
			return RACZEJ_NIEPEWNY;
		else if(confidenceName.equals("Niepewny"))
			return NIEPEWNY;
		else
			return null;
	}
}

class SerachResultRecord extends ListGridRecord {
	
	SerachResultRecord() {}
	SerachResultRecord( long objectId, String objectName, double objectConfidence ) {
		setObjectId(objectId);
		setObjectName(objectName);
		setObjectConfidence(objectConfidence);
	}
	public void setObjectName( String objectName ) {
		this.setAttribute("objectName", objectName);
	}
	
	public void setObjectConfidence( double objectConfidence ) {
		this.setAttribute("objectConfidence", objectConfidence);
	}
	
	public void setObjectId( long objectId ) {
		this.setAttribute("objectId", objectId);
	}
}

class SerachResultDataSource extends DataSource {
	
	//private static SerachResultDataSource instance = null;  
	
	/*
    public static SerachResultDataSource getInstance() {  
        if (instance == null) {  
            instance = new SerachResultDataSource("searchDS");  
        }  
        return instance;  
    }  
	*/
	public SerachResultDataSource(String id) {
		setID(id);  
        setTitleField("objectName");
        
        DataSourceIntegerField objectId = new DataSourceIntegerField("objectId", "Object ID");  
        objectId.setHidden(true);
        objectId.setPrimaryKey(true);
        
        DataSourceTextField objectName = new DataSourceTextField("objectName", "Innowacja");
        DataSourceFloatField objectConfidence = new DataSourceFloatField("objectConfidence", "Pewność", SearchObjects.PEWNOSC_COLUMN_SIZE);
        setFields(objectId, objectName, objectConfidence);
        setClientOnly(true);
	}
}
